MDEV-37482: Contention on btr_sea::partition::latch; introduce innodb_adaptive_hash_index_cells - #4264
Conversation
|
|
| static MYSQL_SYSVAR_UINT(adaptive_hash_index_cells, btr_search.n_cells, | ||
| PLUGIN_VAR_RQCMDARG, | ||
| "Number of adaptive hash table cells", | ||
| nullptr, innodb_adaptive_hash_index_cells_update, 0, 0, UINT_MAX, 0); | ||
| #endif /* BTR_CUR_HASH_ADAPT */ |
There was a problem hiding this comment.
@iMineLink pointed out that this forms an artificial limitation on really large buffer pools. This would have to be size_t instead of uint.
Furthermore, I’d like to see if we could repurpose innodb_adaptive_hash_index_parts. That is, hard-wire the partitions to 1, and make that parameter control the hash table size. Possibly, it could be feasible to replace the btr_sea::partition::latch with latches that are embedded in the hash array, like we do it for buf_pool.page_hash and lock_sys.rec_hash.
There was a problem hiding this comment.
If the number of partitions becomes hardwired to 1, I believe that having a size_t variable for the number of cells may be less interesting as the CRC32C does not provide enough bits of entropy to distribute the values over more than 232-1 cells, making uint wide enough. If wider hash would be implemented (xxHash could be an interesting candidate), it would make more sense to switch to size_t.
There was a problem hiding this comment.
Right, I did not realize that the uint actually corresponds to the available entropy of CRC-32C. Anything larger than that definitely is useless.
We actually have an implementation of xxHash in the rocksdb submodule. For some reason, its AVX-512 implementation failed to compile in my environment, and I had commented it out:
diff --git a/util/xxhash.h b/util/xxhash.h
index 9846861b7..d38c83ef5 100644
--- a/util/xxhash.h
+++ b/util/xxhash.h
@@ -2745,7 +2745,7 @@ enum XXH_VECTOR_TYPE /* fake enum */ {
#endif
#ifndef XXH_VECTOR /* can be defined on command line */
-# if defined(__AVX512F__)
+# if 0&&defined(__AVX512F__)
# define XXH_VECTOR XXH_AVX512
# elif defined(__AVX2__)
# define XXH_VECTOR XXH_AVX2It would be interesting to test the relative performance of this, compared to CRC-32C, on a few different processor implementations (one with AVX512 for both, and another comparing the AVX2 implementation to crc32c_3way()). While doing this, we must keep in mind that dtuple_fold() is currently computing a hash piecewise, one field at a time. It looks like XXH64_update() in the above code would support appending any number of bytes to the hash. It looks like we may have more comprehensive cross-ISA SIMD coverage for our crc32 implementations than for xxHash.
There was a problem hiding this comment.
The following would avoid the compilation error without disabling the AVX512 implementation:
diff --git a/util/xxhash.h b/util/xxhash.h
index 9846861b7..a5742a157 100644
--- a/util/xxhash.h
+++ b/util/xxhash.h
@@ -3658,7 +3658,7 @@ XXH3_scrambleAcc_avx512(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)
}
}
-XXH_FORCE_INLINE XXH_TARGET_AVX512 void
+XXH_TARGET_AVX512 void
XXH3_initCustomSecret_avx512(void* XXH_RESTRICT customSecret, xxh_u64 seed64)
{
XXH_STATIC_ASSERT((XXH_SECRET_DEFAULT_SIZE & 63) == 0);This patch is apparently only needed with CMAKE_BUILD_TYPE=Debug, not with CMAKE_BUILD_TYPE=RelWithDebInfo.
The upstream source code https://github.com/Cyan4973/xxHash is more up to date and includes a benchmark:
make -C tests/bench clean benchHash_avx512
tests/bench/benchHash_avx512Compared to the plain benchHash, the benchHash_avx512 appears to speed up xxh3 and XXH128 only. I understood that there is a 64-bit and a 128-bit variant of XXH3, which the benchmark is referring to with the names xxh3 and XXH128.
The interface to the XXH32 function seems to be compatible with crc32 functions. I added the crc32_avx512.cc from https://github.com/dr-m/crc32_simd to the directory and patched the code to make use of it:
diff --git a/tests/bench/Makefile b/tests/bench/Makefile
index ec5d56f..974a2f7 100644
--- a/tests/bench/Makefile
+++ b/tests/bench/Makefile
@@ -36,7 +36,7 @@ CXXFLAGS ?= -O3
LDFLAGS += $(MOREFLAGS)
-OBJ_LIST = main.o bhDisplay.o benchHash.o benchfn.o timefn.o
+OBJ_LIST = main.o bhDisplay.o benchHash.o benchfn.o timefn.o crc32_avx512.o
default: benchHash
diff --git a/tests/bench/hashes.h b/tests/bench/hashes.h
index 39f6e0f..d4f3c8f 100644
--- a/tests/bench/hashes.h
+++ b/tests/bench/hashes.h
@@ -66,10 +66,12 @@
#define XXH_INLINE_ALL
#include "xxhash.h"
+unsigned crc32c_refl_vpclmulqdq(unsigned crc, const void *buf, size_t size);
+
size_t XXH32_wrapper(const void* src, size_t srcSize, void* dst, size_t dstCapacity, void* customPayload)
{
(void)dst; (void)dstCapacity; (void)customPayload;
- return (size_t) XXH32(src, srcSize, 0);
+ return (size_t) crc32c_refl_vpclmulqdq(0, src, srcSize);
}
I also worked around a warning from GCC 15.2.0 elsewhere:
diff --git a/tests/test_alias.c b/tests/test_alias.c
index af1065f..0ed4925 100644
--- a/tests/test_alias.c
+++ b/tests/test_alias.c
@@ -7,7 +7,7 @@
int main() {
// it seems this has to be exactly 24 bytes.
union {
- char x[24];
+ char x[24] __attribute__((nonstring));
// force 8-byte alignment without making
// aliasable with uint64_t.
void *y[3];The numbers that are output by this single-threaded test seem to be proportional to the execution time. Below is the output from the above patched program for an AMD Ryzen AI 9 HX 370:
=== benchmarking 4 hash functions ===
benchmarking large inputs : from 512 bytes (log9) to 128 MB (log27)
xxh3 , 74182, 84666, 83672, 89621, 92826, 94608, 95333, 95214, 95421, 95539, 95428, 92181, 89884, 91424, 93322, 74003, 61454, 55054, 54935
XXH32 , 50964, 59345, 66989, 74916, 76056, 76814, 77486, 77244, 77221, 75709, 78064, 77477, 76820, 76725, 77119, 64710, 65586, 67875, 61154
XXH64 , 23776, 25692, 26763, 27317, 27243, 27885, 28019, 27526, 27998, 27915, 26876, 27732, 27498, 27587, 27589, 26237, 26248, 26817, 27648
XXH128 , 47036, 67880, 77207, 84151, 90032, 86994, 90539, 91385, 90459, 93035, 93205, 86592, 85137, 86459, 86074, 65815, 62117, 58866, 52468
Throughput small inputs of fixed size (from 1 to 30 bytes):
xxh3 , 684966002, 660267932, 686242542, 591918279, 593796881, 653788552, 691280352, 693917070, 796122351, 799086322, 606649579, 607106262, 743145838, 770496269, 773394061, 777579358, 538555002, 532533910, 552009941, 548027883, 543334100, 540782406, 531313570, 531370730, 536021827, 535807626, 533730883, 507836101, 529489272, 527372639
XXH32 , 391192227, 394170674, 392500119, 320799639, 325310066, 300092059, 325021742, 325166174, 319339892, 324440142, 320935576, 319710875, 318605694, 320033480, 318768959, 321140626, 266827038, 269546291, 270451691, 271340836, 271642933, 268264601, 270806888, 263607977, 267720899, 268822868, 266933926, 253647371, 269115020, 269411779
XXH64 , 531855115, 500845328, 445383908, 560522481, 466170811, 401734154, 353106295, 465769876, 387646727, 348885765, 313642848, 373218102, 330846547, 292677619, 263810140, 379560978, 331417038, 284102612, 262724111, 314605881, 275802854, 247115565, 227006968, 313150520, 271040908, 250206062, 235322131, 264888019, 239329223, 218043430
XXH128 , 600416903, 598992972, 597492462, 597645528, 600791325, 598841509, 600595595, 602564178, 543290108, 551507908, 559672652, 567830015, 572610884, 573292836, 461124110, 568812453, 441289653, 443379326, 449714793, 445896308, 443586459, 441661817, 452889973, 451724824, 355037442, 454808260, 453913239, 455387883, 445214930, 434933402
benchmarking random size inputs [1-N] :
xxh3 , 536254141, 537572868, 538169107, 530058591, 554132343, 567626107, 574962298, 574064510, 575911003, 512575947, 733187750, 730542641, 717504120, 745609269, 744037097, 743641148, 700682822, 680405902, 658648507, 654970094, 643835364, 633237371, 650883337, 651155217, 645069308, 643558465, 641581970, 633572643, 632410158, 635136736
XXH32 , 357112193, 380404113, 393745929, 279481611, 328882531, 327669975, 326555116, 323169043, 304338634, 296146461, 284067481, 285193023, 261837568, 261916119, 271470126, 286578410, 297919080, 310922451, 317438909, 308153526, 310695050, 237882917, 306093451, 292329079, 304391960, 292037006, 301689552, 294104782, 297568491, 288948386
XXH64 , 586983878, 540011057, 505108609, 515782962, 506867672, 482203869, 458474345, 460857782, 454959882, 444087636, 436830029, 426223145, 414820438, 404221782, 389029293, 392782728, 383694624, 373786265, 372277845, 369071752, 358965895, 355644767, 343765355, 345120575, 332244312, 330058777, 327488924, 324763345, 328342498, 316925302
XXH128 , 600494980, 601024972, 600815707, 709364018, 721656467, 717393849, 728587806, 727638953, 714389847, 640170770, 704909059, 691095633, 677935985, 671790219, 664878820, 661493496, 634991187, 617963404, 614205735, 600351968, 591558571, 582670037, 572910083, 570938552, 561659226, 552558359, 551863000, 543461642, 544238249, 540090042
Latency for small inputs of fixed size :
xxh3 , 232758925, 231240688, 235893537, 218715797, 218702972, 217121209, 215070339, 216124609, 228496964, 227321150, 220489768, 216466240, 225549489, 222822477, 218329570, 228193366, 199722428, 202750981, 207964315, 205000677, 211305233, 204392876, 203269104, 208302695, 207763940, 205726991, 203989265, 192116024, 202467348, 205083400
XXH32 , 141043491, 140301324, 140486628, 98556109, 98245408, 98513733, 98804565, 98542229, 96771917, 96485345, 97056348, 94577797, 99446605, 99849828, 98193147, 105409603, 85836960, 86520583, 85472248, 85250394, 86339994, 85767916, 86837601, 86207302, 86573186, 86054076, 84703667, 85890112, 85643206, 85543224
XXH64 , 192012704, 162931329, 140704020, 186484149, 155708976, 135887600, 119828833, 161083460, 136889778, 118022610, 108682607, 134063193, 119996471, 107955849, 95983286, 134099504, 119074090, 93820245, 96247846, 116644599, 104156252, 95846157, 86348288, 114379316, 105948087, 95571192, 87200480, 101708869, 92938617, 85751257
XXH128 , 236321318, 236073631, 236102127, 208280715, 208310530, 210537461, 207243248, 210688513, 194382849, 193552942, 191795246, 192578612, 193381769, 194508669, 192642081, 194463399, 203166631, 203207549, 194373178, 195655373, 192597790, 200018834, 198876272, 202741660, 200240055, 193788601, 199949428, 196226837, 193538519, 202656164
Latency for small inputs of random size [1-N] :
xxh3 , 235249462, 235093356, 235020196, 230137534, 226608695, 225257538, 223406822, 222481072, 220464520, 220366994, 220493278, 220447660, 221115749, 221203118, 220894785, 222059533, 220315846, 219357725, 218859180, 219266622, 218436838, 217102632, 217388236, 214020849, 216201591, 215447083, 214364303, 215011443, 214583615, 213633500
XXH32 , 138574687, 138200659, 138254096, 127152154, 118652610, 116125087, 113038971, 111430621, 109049625, 107047720, 106949323, 105718789, 104509137, 104077495, 103943496, 103957514, 102501662, 101947719, 101586218, 100532803, 99238931, 98585253, 97934961, 96996536, 96221852, 95664977, 95513748, 95093612, 95705998, 94256848
XXH64 , 191493620, 173300634, 163516791, 167001254, 166128454, 158375539, 152604393, 153758844, 151630496, 147949428, 144272111, 141345000, 138796754, 136163707, 132040948, 133526774, 131023326, 128485376, 128065667, 127330599, 126536183, 124805157, 121684005, 122473701, 119697993, 117956051, 117532869, 116771538, 117506207, 114484195
XXH128 , 235632251, 236305541, 235991633, 228243862, 223842736, 222420190, 219975757, 218645414, 214840004, 210478170, 210057345, 207610543, 205595771, 204385614, 203421740, 202734423, 201489640, 201351797, 202091043, 201638052, 201245985, 201648995, 200984775, 200011769, 199330525, 199704794, 198743103, 198247503, 199099688, 198201541
For the first output, the CRC-32C-disguised-as-XXH32 is reporting 3 to 6 times the numbers that the genuine XXH32 would report. While this easily beats the unaccelerated (?) XXH64, the 64-bit xxh3 seems to be a clear winner.
That is, it could be worth the effort to implement the 64-bit xxh3() as an alternative for rec_fold() and dtuple_fold() in a separate piece of work. However, we must keep in mind that the above benchmark is not at all covering cases where a hash is being computed piecewise, like it is the case in dtuple_fold() where we invoke my_crc32c() on each index field separately. In fact, it is dtuple_fold() that is being executed most of the time. That the rec_fold() is tail-calling my_crc32c() on a contiguous buffer only benefits AHI modifications, not key lookups.
|
5ff7fec is a start of improving this further. It needs to be combined with the previous changes, that is, introducing |
f87c07d to
7430887
Compare
| "Redo log write size to avoid read-on-write; must be a power of two", | ||
| nullptr, nullptr, 512, 512, 4096, 1); | ||
|
|
||
|
|
There was a problem hiding this comment.
Assertion found while testing MDEV-37482
origin/MDEV-37482 7430887b8069b990194b04eff2597fcdceab9470
# 2025-09-19T03:20:49 [2441544] | 2025-09-19 3:20:38 22 [ERROR] mariadbd: Deadlock found when trying to get lock; try restarting transaction
# 2025-09-19T03:20:49 [2441544] | mariadbd: /data/Server/MDEV-37482/storage/innobase/btr/btr0btr.cc:1109: dberr_t dict_index_t::clear(que_thr_t*): Assertion `!any_ahi_pages()' failed.
Stacktrace
# 2025-09-19T03:24:21 [2441544] #0 __pthread_kill_implementation (no_tid=0, signo=6, threadid=140302231103040) at ./nptl/pthread_kill.c:44
# 2025-09-19T03:24:21 [2441544] #1 __pthread_kill_internal (signo=6, threadid=140302231103040) at ./nptl/pthread_kill.c:78
# 2025-09-19T03:24:21 [2441544] #2 __GI___pthread_kill (threadid=140302231103040, signo=6) at ./nptl/pthread_kill.c:89
# 2025-09-19T03:24:21 [2441544] #3 0x000055be1e39e4ac in my_write_core (sig=6) at /data/Server/MDEV-37482/mysys/stacktrace.c:424
# 2025-09-19T03:24:21 [2441544] #4 0x000055be1db572a4 in handle_fatal_signal (sig=6) at /data/Server/MDEV-37482/sql/signal_handler.cc:298
# 2025-09-19T03:24:21 [2441544] #5 <signal handler called>
# 2025-09-19T03:24:21 [2441544] #6 __pthread_kill_implementation (no_tid=0, signo=6, threadid=140302231103040) at ./nptl/pthread_kill.c:44
# 2025-09-19T03:24:21 [2441544] #7 __pthread_kill_internal (signo=6, threadid=140302231103040) at ./nptl/pthread_kill.c:78
# 2025-09-19T03:24:21 [2441544] #8 __GI___pthread_kill (threadid=140302231103040, signo=signo@entry=6) at ./nptl/pthread_kill.c:89
# 2025-09-19T03:24:21 [2441544] #9 0x00007f9add550476 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
# 2025-09-19T03:24:21 [2441544] #10 0x00007f9add5367f3 in __GI_abort () at ./stdlib/abort.c:79
# 2025-09-19T03:24:21 [2441544] #11 0x00007f9add53671b in __assert_fail_base (fmt=0x7f9add6eb130 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x55be1e8a58c2 "!any_ahi_pages()", file=0x55be1e8a5ce0 "/data/Server/MDEV-37482/storage/innobase/btr/btr0btr.cc", line=1109, function=<optimized out>) at ./assert/assert.c:92
# 2025-09-19T03:24:21 [2441544] #12 0x00007f9add547e96 in __GI___assert_fail (assertion=0x55be1e8a58c2 "!any_ahi_pages()", file=0x55be1e8a5ce0 "/data/Server/MDEV-37482/storage/innobase/btr/btr0btr.cc", line=1109, function=0x55be1e8a7548 "dberr_t dict_index_t::clear(que_thr_t*)") at ./assert/assert.c:101
# 2025-09-19T03:24:21 [2441544] #13 0x000055be1e18ea7e in dict_index_t::clear (this=this@entry=0x7f9a40048e98, thr=thr@entry=0x7f9a40026d98) at /data/Server/MDEV-37482/storage/innobase/btr/btr0btr.cc:1109
# 2025-09-19T03:24:21 [2441544] #14 0x000055be1e0ba632 in dict_table_t::clear (this=<optimized out>, thr=thr@entry=0x7f9a40026d98) at /data/Server/MDEV-37482/storage/innobase/row/row0log.cc:3798
# 2025-09-19T03:24:21 [2441544] #15 0x000055be1e32566e in row_undo_ins (node=node@entry=0x7f9a400b1178, thr=thr@entry=0x7f9a40026d98) at /data/Server/MDEV-37482/storage/innobase/row/row0uins.cc:625
# 2025-09-19T03:24:21 [2441544] #16 0x000055be1e1080fc in row_undo (node=node@entry=0x7f9a400b1178, thr=thr@entry=0x7f9a40026d98) at /data/Server/MDEV-37482/storage/innobase/row/row0undo.cc:401
# 2025-09-19T03:24:21 [2441544] #17 0x000055be1e109418 in row_undo_step (thr=thr@entry=0x7f9a40026d98) at /data/Server/MDEV-37482/storage/innobase/row/row0undo.cc:442
# 2025-09-19T03:24:21 [2441544] #18 0x000055be1e03473d in que_thr_step (thr=thr@entry=0x7f9a40026d98) at /data/Server/MDEV-37482/storage/innobase/que/que0que.cc:551
# 2025-09-19T03:24:21 [2441544] #19 0x000055be1e034a07 in que_run_threads_low (thr=thr@entry=0x7f9a40026d98) at /data/Server/MDEV-37482/storage/innobase/que/que0que.cc:609
# 2025-09-19T03:24:21 [2441544] #20 0x000055be1e034ace in que_run_threads (thr=0x7f9a40026d98) at /data/Server/MDEV-37482/storage/innobase/que/que0que.cc:629
# 2025-09-19T03:24:21 [2441544] #21 0x000055be1e158866 in trx_t::rollback_low (this=this@entry=0x7f9ad4441a80, savept=savept@entry=0x0) at /data/Server/MDEV-37482/storage/innobase/trx/trx0roll.cc:121
# 2025-09-19T03:24:21 [2441544] #22 0x000055be1e15b17d in trx_rollback_for_mysql (trx=trx@entry=0x7f9ad4441a80) at /data/Server/MDEV-37482/storage/innobase/trx/trx0roll.cc:218
# 2025-09-19T03:24:21 [2441544] #23 0x000055be1decb49a in innobase_rollback (thd=<optimized out>, rollback_trx=true) at /data/Server/MDEV-37482/storage/innobase/handler/ha_innodb.cc:4736
# 2025-09-19T03:24:21 [2441544] #24 0x000055be1db5d21a in ha_rollback_trans (thd=thd@entry=0x7f9a40000d58, all=all@entry=true) at /data/Server/MDEV-37482/sql/handler.cc:2376
# 2025-09-19T03:24:21 [2441544] #25 0x000055be1d9a2019 in trans_rollback (thd=thd@entry=0x7f9a40000d58) at /data/Server/MDEV-37482/sql/transaction.cc:386
# 2025-09-19T03:24:21 [2441544] #26 0x000055be1d800c51 in mysql_execute_command (thd=thd@entry=0x7f9a40000d58, is_called_from_prepared_stmt=is_called_from_prepared_stmt@entry=false) at /data/Server/MDEV-37482/sql/sql_parse.cc:5549
# 2025-09-19T03:24:21 [2441544] #27 0x000055be1d802957 in mysql_parse (thd=thd@entry=0x7f9a40000d58, rawbuf=<optimized out>, length=<optimized out>, parser_state=parser_state@entry=0x7f9aa8a55330) at /data/Server/MDEV-37482/sql/sql_parse.cc:7905
# 2025-09-19T03:24:21 [2441544] #28 0x000055be1d804eec in dispatch_command (command=command@entry=COM_QUERY, thd=thd@entry=0x7f9a40000d58, packet=packet@entry=0x7f9a4000b119 " ROLLBACK /* E_R Thread15 QNO 1027 CON_ID 31 */ ", packet_length=packet_length@entry=49, blocking=blocking@entry=true) at /data/Server/MDEV-37482/sql/sql_parse.cc:1903
# 2025-09-19T03:24:21 [2441544] #29 0x000055be1d806ec3 in do_command (thd=thd@entry=0x7f9a40000d58, blocking=blocking@entry=true) at /data/Server/MDEV-37482/sql/sql_parse.cc:1416
# 2025-09-19T03:24:21 [2441544] #30 0x000055be1d98baed in do_handle_one_connection (connect=<optimized out>, connect@entry=0x55be2199e9a8, put_in_cache=put_in_cache@entry=true) at /data/Server/MDEV-37482/sql/sql_connect.cc:1415
# 2025-09-19T03:24:21 [2441544] #31 0x000055be1d98bd2d in handle_one_connection (arg=0x55be2199e9a8) at /data/Server/MDEV-37482/sql/sql_connect.cc:1327
# 2025-09-19T03:24:21 [2441544] #32 0x00007f9add5a2ac3 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:442
# 2025-09-19T03:24:21 [2441544] #33 0x00007f9add634850 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
Core dump is present on pluto:-
/data/results/1758228918/TBR-2335
Bug filed:-https://jira.mariadb.org/browse/MDEV-37697
There was a problem hiding this comment.
This error is still reproducible.
There was a problem hiding this comment.
Hi @dr-m ,
i am still hitting this crash :-
This issue was found here:-
MDEV-37482, origin/MDEV-37482 e0a4a1dc3cfa262266f38871869027c8359e9e4f
# 2025-09-25T17:36:32 [468290] | mariadbd: /data/Server/MDEV-37482A/storage/innobase/btr/btr0btr.cc:1109: dberr_t dict_index_t::clear(que_thr_t*): Assertion `!any_ahi_pages()' failed.
Core dump present on pluto:-
/data/results/1758798531/008361
There was a problem hiding this comment.
a456e7d attempts to address this and adds a few more assertions to catch similar trouble earlier.
vlad-lesin
left a comment
There was a problem hiding this comment.
As it was noted in the first commit message, the idea to use a combination of shared btr_sea::partition::latch and page_hash_latch is similar to the one used to reduce contention on lock_sys.latch. So it should indeed decrease the contention on btr_sea::partition::latch. The code looks good to me, at least I haven't found any errors with just reviewing. RQG testing is necessary to be more sure that the code is correct. Approved to push after RQG testing.
|
|
I squashed this for the final push. The base revision did not change: git diff b5ee026183cfb3add456653424a6e89f5215d633..3560656fc60cdb60023261a18ff91668066d83abdiff --git a/storage/innobase/btr/btr0sea.cc b/storage/innobase/btr/btr0sea.cc
index 20ddc61f35e..7e2ded9f8bb 100644
--- a/storage/innobase/btr/btr0sea.cc
+++ b/storage/innobase/btr/btr0sea.cc
@@ -714,7 +714,8 @@ static uint32_t btr_search_info_update_hash(const btr_cur_t &cursor) noexcept
Without this special handling, we could end up setting totally
useless parameters buf_block_t::LEFT_SIDE | 1 << 16 below
(rebuilding the adaptive hash index on a 1-byte prefix)
- if all compared secondary index were NULL. */
+ for example when page_cur_search_with_match_bytes() finds matches
+ of LIKE 'a%' in the first index field. */
left_bytes_fields|= 1;
else if (left_bytes_fields)
{
@@ -919,12 +920,11 @@ btr_sea::partition::cleanup_after_erase(ahi_node *erase, page_hash_latch *l)
#endif
template<bool ex>
btr_sea::partition::erase_status
-btr_sea::partition::erase(uint32_t fold, const rec_t *rec) noexcept
+btr_sea::partition::erase(hash_chain &cell, const rec_t *rec) noexcept
{
ut_ad(ex ? latch.have_wr() : latch.have_rd());
ut_ad(btr_search.enabled);
- hash_chain &cell{table.cell_get(fold)};
page_hash_latch *const hash_lock{ex ? nullptr : &table.lock_get(cell)};
buf_block_t *block= nullptr;
if (!ex) hash_lock->lock();
@@ -1810,13 +1810,16 @@ void btr_search_update_hash_on_delete(btr_cur_t *cursor) noexcept
ut_ad(btr_search.enabled);
ut_ad(block_index == index);
- btr_sea::partition::erase_status s= part.erase<false>(fold, rec);
+ btr_sea::partition::erase_status s=
+ part.erase<false>(part.table.cell_get(fold), rec);
if (s == btr_sea::partition::ERASE_RETRY)
{
part.latch.wr_lock(SRW_LOCK_CALL);
- if (UNIV_LIKELY(btr_search.enabled))
+ btr_sea::hash_chain &cell{part.table.cell_get(fold)};
+
+ if (UNIV_LIKELY(cell.first != nullptr))
{
- s= part.erase<true>(fold, rec);
+ s= part.erase<true>(cell, rec);
ut_ad(s != btr_sea::partition::ERASE_RETRY);
}
else
diff --git a/storage/innobase/include/btr0sea.h b/storage/innobase/include/btr0sea.h
index 24febbe76f5..e697fc18771 100644
--- a/storage/innobase/include/btr0sea.h
+++ b/storage/innobase/include/btr0sea.h
@@ -312,11 +312,11 @@ struct btr_sea
/** Delete a pointer to a record if it exists, and release the latch.
@tparam ex true=holding exclusive latch, false=shared latch
- @param fold CRC-32C of rec prefix
+ @param cell hash table cell that may contain the CRC-32C of rec prefix
@param rec B-tree leaf page record
@return status */
template<bool ex>
- erase_status erase(uint32_t fold, const rec_t *rec) noexcept;
+ erase_status erase(hash_chain &cell, const rec_t *rec) noexcept;
};
/** number of hash table entries, to be multiplied by n_parts */The first hunk is related to ad8509b; I spent some additional time to understand the The remaining hunks should address the crash that @mariadb-SaahilAlam had been filed as MDEV-37716. |
xtrabackup_backup_func(): Invoke btr_search_sys_create(), because innodb_shutdown() assumes that it will have been called. srv_boot(): Invoke btr_search_sys_create(). This fixes assertion failures in the test innodb.temporary_table. btr_sea::create(): Do not invoke enable(). buf_pool_t::create(): Instead of invoking btr_sea::create(), invoke btr_sea::enable() when needed.
buf_pool_t::clear_hash_index(): Also clear index->search_info.ref_count
btr_search_info_update_hash(): Avoid useless rebuild if cmp==0. Consider index(col) on a VARCHAR column for which we have the values col='prefix1' and col='prefix2'. In WHERE col LIKE 'prefix%', page_cur_search_with_match_bytes() would return 0 as well as 0 matched fields and bytes on each side. It turns out that page_cur_search_with_match_bytes() can only return nonzero matched bytes when a binary comparison can be used, such as with VARBINARY or INT columns. Co-developed by: Alessandro Vetere
To reduce contention between insert, erase and search, let us mimic commit b08448d (MDEV-20612). That is, btr_sea::partition::insert() and btr_sea::partition::erase() will use a combination of a shared btr_sea::partition::latch and a tiny page_hash_latch that is pushed down to the btr_sea::hash_table::array. An exclusive btr_sea::partition::latch will be used in the final part of btr_search_drop_page_hash_index(), where we must guarantee that all entries will be removed, as well as in operations that affect an entire adaptive hash index partition. btr_sea::hash_chain: Chain of ahi_node hash buckets. btr_sea::hash_table: A hash table that includes page_hash_latch interleaved with hash_chain. page_hash_latch::try_lock(): Attempt to acquire an exclusive latch without waiting. btr_search_guess_on_hash(): Acquire also the page_hash_latch in order to prevent a concurrent modification of the hash bucket chain that our lookup is traversing. ha_insert_for_fold(): Remove. Invoke btr_sea::partition::insert() directly. btr_sea::partition::erase(): Add template<bool ex> for indicating whether an exclusive or a shared btr_sea::partition::latch is being held. If the ex=false operation fails to free the memory, btr_search_update_hash_on_delete() will retry with ex=true. btr_sea::partition::cleanup_after_erase(): Add an overload for the case where instead of holding an exclusive latch, we hold a shared latch along with a page_hash_latch. When not holding an exclusve latch, we may fail to free the memory, and the caller has to retry with an exclusive latch. btr_sea::partition::cleanup_after_erase_start(), btr_sea::partition::cleanup_after_erase_finish(): Split from cleanup_after_erase() to reduce the amount of code duplication. btr_sea::partition::block_mutex: Protect only the linked list of blocks. The spare block will exclusively be updated via Atomic_relaxed::exchange(). btr_sea::partition::rollback_insert(): Free the spare block in the unlikely event that the adaptive hash index has been disabled after our invocation of btr_sea::partition::prepare_insert(). ha_remove_all_nodes_to_page(): Merged to the only caller btr_search_drop_page_hash_index(). ssux_lock_impl::wr_rd_downgrade(): Downgrade an X latch to S. srw_lock_debug::wr_rd_downgrade(), srw_lock_impl::wr_rd_downgrade(): Downgrade from exclusive to shared. This operation is unavailable if _WIN32 or SUX_LOCK_GENERIC is defined. btr_search_build_page_hash_index(): Downgrade from exclusive to shared part.latch before starting to insert records into the adaptive hash index. In multi-batch operation, we preserve the last fr[] value in order to ensure the correct operation when buf_block_t::LEFT_SIDE is not set.
SET GLOBAL innodb_adaptive_hash_index_cells may be executed while the server is running. This parameter will be effectively multiplied by innodb_adaptive_hash_index_parts, because each partition will contain its own hash table. Previously, the number of hash table cells in the InnoDB adaptive hash index depended on the initial innodb_buffer_pool_size and was insufficient for some workloads, leading to excessively long hash bucket chains. If innodb_adaptive_hash_index_cells is at its minimum and default value 16381 at startup, it will be derived from the innodb_buffer_pool_size, for backward compatibility.
Description
The number of hash table cells in the InnoDB adaptive hash index was fixed on the initial
innodb_buffer_pool_sizeand insufficient for some workloads, leading to excessively long hash bucket chains.Furthermore,
btr_sea::partition::insert()andbtr_sea::partition::erase()operations will be optimized to prefer a combination of a sharedlatchand apage_hash_lockthat is pushed down to the hash table. In this way, these operations can run concurrently with each other as well as searches on other parts of the hash table of the samebtr_sea::partition.Release Notes
We introduce the parameter
innodb_adaptive_hash_index_cellsthat can be configured withSET GLOBAL. The specified value will be effectively multiplied byinnodb_adaptive_hash_index_parts, because each partition will contain its own hash table.How can this PR be tested?
Basing the PR against the correct MariaDB version
mainbranch.PR quality check